Hey @zep, not sure if this is a bug or intended, but I just realized that, in a fresh cart, sfx 0 is speed 1, while all other sfx are speed 16.
Is there some reason for this?
Seems like this is something that might lead to confusion at times. The user will probably figure out what's different pretty quickly, but still... I thought I should at least put it on your radar as a possible mistake.
As an aside, "Speed" really isn't the right term here. It should be "(note) duration", or something similar. I dunno, I don't have an audio background so there's probably a more concise term.
In my qsort() thread:
https://www.lexaloffle.com/bbs/?tid=38679
If you click the "Code" button on the embedded cart and scroll down to qsort() or iqsort(), you'll see a line near the top of each function that says, if l then, but the line inside the cart is actually if l<r then, so if anyone grabs the code for the function, they get a corrupted version of it.
I'm guessing this, and possibly other, reserved HTML elements are not being escaped properly...?

A while back I posted an implementation of an in-place dual-pivot quicksort, which is the default sort algorithm most standard libraries offer these days. I've since tweaked it a bit to save a few tokens, and today I wrote up a sample cart that does some primitive testing as an example of usage.
This includes both a general 221-token qsort(), which can accept a custom comparator function (defaults to a less-than comparator for ascending order), and a tweaked 199-token iqsort(), which inlines the comparisons as simple "<" operators, producing a smaller and faster sort in return for the sort order and index not being customizable.
See tab 0's header comment for more details.
(Side note: I realized while implementing comparators that you could sneak in shuffle functionality just by sorting with a random coin-flip comparator. Handy.)
Edit: WARNING! Do NOT grab the function from the "Code" flyout on the embedded cart below! There is a bug on the BBS right now that deletes a "<" comparison! Click the "Cart" button to download the .p8.png version!



Yo @zep,
This thread isn't the first time I've seen people ask about inserting values into the middle or start of arrays/sequences:
https://www.lexaloffle.com/bbs/?tid=38249
It occurs to me that a lot of carts probably have similar boilerplate code like the ins() function I wrote for that person. I think it would be nice, and better for PICO-8's host-machine performance, if there were a C-side implementation of that insert code, and I think you could do it simply by taking an optional third argument to add(), effectively implementing something like this Lua code on the C side:
function add(t,v,i) i=i or #t+1 -- default to extending the list for j=#t,i,-1 do t[j+1]=t[j] end t[i]=v return v -- return the added value for convenience end |
This shouldn't break any existing code, since there hasn't previously been a third arg, and the default value produces the existing behavior.
(Come to think of it, I'm not sure if you have add() on the C side or as hidden Lua. If it's not already on the C side, you might want to put it there, because it happens a lot in carts and doing it through interpreted code is definitely going to slow things down on the host hardware. Same goes for any other oft-called hidden Lua code.)
I have a cart used as an ongoing reminder alarm, simply showing the previous alarm, the current time, and the next alarm. It runs continuously for very long periods, e.g. weeks. Indeed, this instance has been running since the week 0.2.0i came out.
Today, for the first time I've ever noticed, the display was showing a pattern of corruption. I took a screenshot, but there was no corruption in the screenshot, so I tried saving a gif. I have my gif len set to a couple of minutes, so the result is quite long.
If you pay attention, the gif shows the parts of the pattern changing every second or three:

And yet when I saved a screenshot at the same time, there was no evidence of the corruption:

I assume this is because the PNG is saved from a point in the pipeline that comes before the corruption, while the GIF is saved after the corruption.
This means the cart itself isn't producing the corruption. It's happening somewhere in the frame presentation pipeline.

I'm surprised I haven't noticed this before today.
If I have my tabs set to two spaces, and then I cursor up or down across lines with varying numbers of tabs indenting them, the cursor column will shift left or right depending on the number of tabs at the start of the line. See this example gif for a demonstration:

Edit: as I discovered below, this also happens with double-wide glyphs:

The editor should be trying to maintain a virtual on-screen column, not an in-document column.



Yo @zep,
Instead of just turning the corner performance/stats graph on and off, maybe cycle through off, current size, and something closer to the full screen?
This could allow showing twice as much history on the graph, as well as showing a finer resolution of time within each tick. Right now we're only seeing 1-2 seconds (depending on _update/_update60) and the vertical resolution is very limited.
The large view might also accommodate more information that's not currently in the corner view. I'm not sure what information to choose—I'm just throwing the idea out there for you to think about.
Whatcha think?






Hey @zep,
So we've discovered that 0x5f5e is a destination write mask if it's between 1 and 15, such that the write is now presumably something like this:
dest = (dest & ~writemask) | (color & writemask)
It'd be really great if the top four bits of 0x5f5e were a read mask, allowing us to select bitplanes from source pixels/colors:
dest = (dest & ~writemask) | (color & writemask & readmask)
This would be nice for packing fonts and such. It's already doable with pal(), that's true, but you have to set the entire palette to make it work, whereas you could set just the relevant colors with a read mask. Like, if you have a 1-bit font encoded into four layers, and you're picking the second layer, you'd only need to set pal(2,col) to make it work, instead of all 16.


Lowwwww-priority:
I often have several instances of PICO-8 running. It would be nice if their window titles reflected what was running, at least to some extent, so I could select the right minimized app from the taskbar.
Seems like "documentname - appname" is the de facto standard for this kind of thing, so it'd be nice to click on the taskbar and see this list:
- UNTITLED - PICO-8 (or maybe just PICO-8 when nothing's been saved)
- TIMER.P8 - PICO-8
- CELESTE.P8.PNG - PICO-8
- BUGREPRO.P8 - PICO-8
I converted the filenames to uppercase here because it feels on-brand, so to speak, and also because making uppercase the default would interact nicely with this optional upgrade:
You could extend the titling algorithm so it uses the same method a .p8.png image uses, where if the first line is a comment, it treats it as the cart's title.
For instance, when running/editing this infloop.p8 cart:
The window would be titled "Infinite Loop - PICO-8", rather than "INFLOOP.P8 - PICO-8", because I used a comment (with mixed case) to make a nice, elegant title for my cart.

The slide effect works great on a loop that starts at a note greater than 0, sliding smoothly from the final note of the loop back to the first, but if the loop starts at note 0, it steps instead of sliding.
This doesn't feel like expected/reasonable behavior to me.
Here's a repro/demo that lets you swap loop points, swap volume vs. pitch sliding, and swap sine wave vs. noise.

If you display the code on this cart, you'll see some unknown symbols in the header comment.
Here's a comparison of how they look in PICO-8 vs. how they look on the BBS:

I assume this means the BBS doesn't do the glyph->unicode conversion trick.

Note: @zep, please have patience reading this, as I think there's more than one thing going on here.
I had to fix @Reload's "Pico-Sprint" cart here.
For whatever reason, they were choosing to make empty-arg func() calls as func"", possibly in an obsolete attempt to save a token.
The problem is, the call to clip"" screwed up the clip rectangle, because apparently clip() is interpreting the single blank string argument instead of ignoring it. I'm not sure if that qualifies as a bug, since Lua and PICO-8 expect strings to be coerced into numbers in many instances, so it may just be expected behavior that wasn't previously working as expected. I checked to see if maybe the single-argument format was meant to work with a table, e.g. clip{0,0,128,128}, but that did not seem to work.
However, there's more... ← and here begins the second thing
In the process of debugging this, I tried getting the existing clip rectangle from clip()'s return value. I tried these:

I was tinkering with the custom key repeat settings in 0x5f5c and 0x5f5d and I realized that they always seem to be expressed in 30ths of a second. Shouldn't this depend on whether or not the game has _update60(), or for games with custom loops, whether or not they've called _set_fps(60)?
I guess it's not a critical problem if it stays this way, it just seems like it ought to track the fps setting.

Hey @zep, me again. ;)
I looked through the rather comprehensive list at https://rosettacode.org/wiki/Bitwise_operations and couldn't spot anyone at all who had an operator for rotation, let alone find some kind of standard for it. Most languages use either a function or a textual operator (e.g. a ror b), but those end up making your expressions a lot larger and/or filled with whitespace.
WE COULD BE THE ONES TO SET THE STANDARD! :D
I'll just propose a few ideas. Note that I bring the "|" operator into some of them because normally people have to do rotates by or'ing together two shifted values.
rotl rotr ---------- ---------- a <<<< b a >>>> b a <<> b a <>> b -- I like these best, personally a >|> b a <|< b a |>> b a <<| b a >>| b a |<< b |
I like <<> and <>> because they imply that part of the shift wraps back around. I also find them aesthetically pleasing.




I was going through my old posts, gleefully marking bug after bug "resolved" (THANKS ZEP!:D), and ran across one I hadn't actually posted in the support section.
I know the chat section sees a lot of traffic and moves quickly, so I'm worried it was never seen, and I want to try posting it again in the right section, in hopes of seeing it added to 0.2.0 or a later version:
I'm trying to write a tool that has text editing, and I find that the devkit keyboard doesn't return a lot of the special keys that it easily could.
You're returning a string, so there's no reason why it has to be just one character. So pressing the Home key could simply return the string "home". No need for special characters, escape sequences, etc., since these verbose names would all be distinct from any single regular typed character.
I'm mainly thinking of the standard navigation cluster: up, down, left, right, ins, del, home, end, pgup, pgdn, but I'm sure there are others.
There's currently no way to get the existing random seed, since srand() doesn't return anything.
Test/demo:
Could it return the existing seed so we can temporarily change to a sub-system's ongoing seed, then restore it? Like this, for instance:
function handle_ai(ai) local old_seed=srand(ai.seed) ⋮ (stuff) ⋮ srand(old_seed) end |
It's minor, since you can always keep your seeds in shadow values from the outset and manually set them each time, but it'd still be handy.
Thanks! :)




EDIT: I just realized run
already takes an argument to serve as the breadcrumb from another cart. So this isn't an option. Never mind, nothing to see here.
Presently, to load+run you literally have to load blahblah.p8 and then run.
Would it be a bother to run the "run" code through the same line parsing that handles "load", and then auto-run it afterward?
I ask because I was running a bunch of local carts from the command line and it was a tiny bother to have to do two steps each time.
...YES, I realize this is a very minor thing, but hey, why not mention it? The worst that happens is that it doesn't get implemented, right? XD
... uh... r—right...?